#include "CardReader.h"
#include "A6_30_API.h"
#include "zreader.h"
#include "Trf32.h"
#include "myIOmem3.h"
#include "mwCardReader.h"
#include "CRT_310.h"

CardReader::CardReader(QObject *parent, int _dev) : QObject(parent)
{
    moveToThread(&worker);
    fsdev = 0;
    ztdev = 0;
    t10dev = -1;
    r6dev = INVALID_HANDLE_VALUE;
    hDev = INVALID_HANDLE_VALUE;
    dev = _dev;
    connect(this, SIGNAL(readReq(int)), this, SLOT(doReadReq(int)), Qt::QueuedConnection);
    connect(this, SIGNAL(writeReq(QByteArray,QByteArray,QByteArray,int)),
            this, SLOT(doWriteReq(QByteArray,QByteArray,QByteArray,int)), Qt::QueuedConnection);

    worker.start();

    emit readReq(3); //退卡
}

void CardReader::doReadReq(int mode)
{
    switch (mode)
    {
    case 1: //读烟农卡
    case 2: //读卷烟卡
    {
        #ifdef __A6DEV
        readFS(mode);
        #endif
        #ifdef __ZTDEV
        readZT(mode);
        #endif
        #ifdef __T10DEV
        readT10(mode);
        #endif
        read(mode);
    }break;
    case 3:
    {
        #ifdef __A6DEV
        exitCard();
        #endif
        #ifdef __ZTDEV
        openDevZT();
        #endif
        #ifdef __T10DEV
        openDevT10();
        exitCard();
        #endif

        openDev();
        exitCard();
    }break;
    }
}

void CardReader::doWriteReq(QByteArray data, QByteArray keyb, QByteArray blk3, int mode)
{
    write(data, keyb, blk3, mode);
}

#ifdef __A6DEV
void CardReader::exitCard()
{
    if (fsdev == 0)
    {
        if (A6_Connect(2, 9600, &fsdev) != 0)
        {
            sendMsg(0, "打开读卡设备失败");
            return;
        }
    }

    A6_MoveCard(fsdev, MOVE_TOGATEPOS);
    A6_PermitInsertion(fsdev, 0);
    A6_LedControl(fsdev, LED_BLINK);
}

/*
  富士通读卡
  mode : 1 - 只读卡号
         2 - 读所有区
*/
void CardReader::readFS(int mode)
{
    QByteArray buf(16, 0);
    QByteArray key(6, 0);
    QByteArray data;

    if (!openDevFS())
        return;

    sendMsg(0, "正在读卡");

    if (!readBlockFS(4, buf, key)) //卡号区
        goto out;

    data += buf;
    if (mode == 1)
    {
        goto out;
    }

    for (int b = 8; b < 64; b ++) //共64块
    {
        if (b == (((b+1)/4)*4 - 1))
            continue;//跳过控制块

        if (readBlockFS(b, buf, key))
        {
            if (buf.at(0) == 0)
                break;

            data += buf;
        }
        else
        {
            break;
        }
    }

out:
    emit sendMsg(0, "读卡结束");
    emit sendMsg(mode, data); //将数据发送到界面
}

bool CardReader::readBlockFS(int b, QByteArray &buf, QByteArray &key)
{
    BLOCKBUF bb;

    if (b%4 == 0)//读新扇区前教研密钥
    {
        if (!authenFS(b, key, 1))
            return false;
    }

    if(0 != A6_S50ReadOneBlock(fsdev, b/4, b%4, bb))
    {
        emit sendMsg(0, "读扇区失败");
        return false;
    }

    memcpy(buf.data(), &bb, 16);

    return true;
}

bool CardReader::openDevFS()
{
    if (fsdev == 0)
    {
        if (A6_Connect(2, 9600, &fsdev) != 0)
        {
            sendMsg(0, "打开读卡设备失败");
            return false;
        }
    }

    if (A6_S50Select(fsdev) != 0)
    {
        sendMsg(0, "扫卡失败");
        return false;
    }

    return true;
}

/*
    mode :1 - 用KeyA写其他区
         :2 - 用KeyB修改他区
         :3 - 用KeyA写所有区
         :4 - 用KeyB修改卡号区
*/
void CardReader::writeFS(QByteArray &data, QByteArray &key, QByteArray &blk3, int mode)
{
    QByteArray buf;
    int pos;
    int b;
    int ktype1 = 1;
    QByteArray keyb;
    int err = 0;

    if (!openDevFS())
        return;

    sendMsg(0, "正在写卡");

    keyb = key;
    if (mode == 1)
    {
        ktype1 = 0;
        keyb = blk3.right(6);
    }
    else if (mode == 3)
    {
        keyb = blk3.right(6);
    }
    else if (mode == 4)
    {
        ktype1 = 0;
    }

    if (mode > 2)
    {
        if (!writeBlockFS(4, data, key, ktype1))
            ;//return;
        if (!writeBlockFS(7, blk3, key, ktype1))
            ;//return;
    }

    for (b = 8, pos = 16; pos < data.size(); b++)
    {
        buf = data.mid(pos, 16);
        if (b == (((b+1)/4)*4 - 1))
            continue;

        if ((b%4 == 0) && (mode == 1 || mode == 3))
        {
            authenFS(b, key, 1);
            if (!writeBlockFS(b + 3, blk3, key, 1))
                err ++;
        }

        if (!writeBlockFS(b, buf, keyb, 0))
            err ++;

        pos += 16;
    }

    if (err)
    {
        sendMsg(0, "写卡结束，有扇区写入异常，请读卡确认");
    }
    else
    {
        sendMsg(0, "写卡结束");
    }
}

/*
 密钥认证
*/
bool CardReader::authenFS(int b, QByteArray &key, int bkeya)
{
    KEYBUF k;
    unsigned char uid[8];
    DWORD len = 8;

    if (A6_S50ReadUID(fsdev, uid, &len) != 0)
    {
        sendMsg(0, "读特征码失败");
        return false;
    }

    memcpy(&k, key.data(), 6);
    if(0!=A6_S50VerifyPassword(fsdev, b/4, bkeya, k))
    {
        sendMsg(0, "密钥认证失败");
        return false;
    }

    return true;
}

bool CardReader::writeBlockFS(int b, QByteArray &buf, QByteArray &key, int bkeya)
{
    BLOCKBUF bb;

    if (buf.size() == 0)
        return true;

    if (b%4 == 0)
    {
        if (!authenFS(b, key, bkeya))
            return false;
    }

    memcpy(&bb, buf.data(), 16);
    if(0 != A6_S50WriteOneBlock(fsdev, b/4, b%4, bb))
    {
        sendMsg(0, "写扇区异常");
        return false;
    }

    return true;
}
#endif

#ifdef __ZTDEV
bool CardReader::openDevZT()
{
    if (ztdev == 0)
    {
        ztdev = ZT_reader_init(255, 9600);
        if (ztdev == 0)
        {
            sendMsg(0, "打开读卡设备失败");
            return false;
        }
    }

    return true;
}

bool CardReader::authenZT(int b, QByteArray &key, int bkeya)
{
    uint8_t uid[8];
    uint8_t len = 8;

    if (ZT_rf_zt_card(ztdev, uid, &len) != 0)
    {
        sendMsg(0, "扫卡失败");
        return false;
    }

    if(0!=ZT_rf_m1_authentication(ztdev, bkeya, b/4, (uint8_t*)key.data()))
    {
        sendMsg(0, "密钥认证失败");
        return false;
    }

    return true;
}

bool CardReader::writeBlockZT(int b, QByteArray &buf, QByteArray &key, int bkeya)
{
    if (buf.size() == 0)
        return true;

    if (b%4 == 0)
    {
        if (!authenZT(b, key, bkeya))
            return false;
    }

    if(0 != ZT_rf_m1_write(ztdev, b, (uint8_t*)buf.data()))
    {
        sendMsg(0, "写扇区异常");
        return false;
    }

    return true;
}

void CardReader::writeZT(QByteArray &data, QByteArray &key, QByteArray &blk3, int mode)
{
    QByteArray buf;
    int pos;
    int b;
    int ktype1 = 0x60;
    QByteArray keyb;
    int err = 0;

    if (!openDevZT())
        return;

    sendMsg(0, "正在写卡");

    keyb = key;
    if (mode == 1)
    {
        ktype1 = 0x61;
        keyb = blk3.right(6);
    }
    else if (mode == 3)
    {
        keyb = blk3.right(6);
    }
    else if (mode == 4)
    {
        ktype1 = 0x61;
    }

    if (mode > 2)
    {
        if (!writeBlockZT(4, data, key, ktype1))
            ;//return;
        if (!writeBlockZT(7, blk3, key, ktype1))
            ;//return;
    }

    for (b = 8, pos = 16; pos < data.size(); b++)
    {
        buf = data.mid(pos, 16);
        if (b == (((b+1)/4)*4 - 1))
            continue;

        if ((b%4 == 0) && (mode == 1 || mode == 3))
        {
            authenZT(b, key, 0x60);
            if (!writeBlockZT(b + 3, blk3, key, 0x60))
                err ++;
        }

        if (!writeBlockZT(b, buf, keyb, 0x61))
            err ++;

        pos += 16;
    }

    if (err)
    {
        sendMsg(0, "写卡结束，有扇区写入异常，请读卡确认");
    }
    else
    {
        sendMsg(0, "写卡结束");
    }
}

bool CardReader::readBlockZT(int b, QByteArray &buf, QByteArray &key)
{
    if (b%4 == 0)//读新扇区前教研密钥
    {
        if (!authenZT(b, key, 0x60))
            return false;
    }

    if(0 != ZT_rf_m1_read(ztdev, b, (uint8_t*)buf.data()))
    {
        emit sendMsg(0, "读扇区失败");
        return false;
    }

    return true;
}

void CardReader::readZT(int mode)
{
    unsigned char uid[8];
    DWORD len = 8;
    QByteArray buf(16, 0);
    QByteArray key(6, 0);
    QByteArray data;

    if (!openDevZT())
        return;

    sendMsg(0, "正在读卡");

    if (!readBlockZT(4, buf, key)) //卡号区
        goto out;

    data += buf;
    if (mode == 1)
    {
        goto out;
    }

    for (int b = 8; b < 64; b ++) //共64块
    {
        if (b == (((b+1)/4)*4 - 1))
            continue;//跳过控制块

        if (readBlockZT(b, buf, key))
        {
            if (buf.at(0) == 0)
                break;

            data += buf;
        }
        else
        {
            break;
        }
    }

out:
    emit sendMsg(0, "读卡结束");
    emit sendMsg(mode, data); //将数据发送到界面
}
#endif

#ifdef __T10DEV
long CardReader::getDevId(void)
{
    return t10dev;
}

void CardReader::exitCard()
{
    myOpenPebble("Evolis KC200");

    mycanclecard();
    myClosePebble();
}

void CardReader::enterCard()
{
    myOpenPebble("Evolis KC200");

    myfeedcard();
    myClosePebble();
}

bool CardReader::openDevT10()
{
    if (t10dev < 0)
    {
        t10dev = dc_init(100, 0);
    }

    if (t10dev < 0)
    {
        sendMsg(0, "打开读卡设备失败");
        return false;
    }

    return true;
}

void CardReader::readT10(int mode)
{
    unsigned long snr;
    QByteArray buf(16, 0);
    QByteArray key(6, 0);
    QByteArray data;

    if (!openDevT10())
        return;

    enterCard();

    if (dc_card(t10dev, 0, &snr) < 0)
    {
        sendMsg(0, "寻卡失败");
        return;
    }

    sendMsg(0, "正在读卡");

    if (!readBlockT10(4, buf, key)) //卡号区
        goto out;

    data += buf;
    if (mode == 1) //只读卡号区
    {
        goto end;
    }

    for (int b = 8; b < 64; b ++) //1扇区不用,共64块
    {
        if (b == (((b+1)/4)*4 - 1))
            continue;//跳过控制块

        if (readBlockT10(b, buf, key))
        {
            if (buf.at(0) == 0)
                break;

            data += buf;
        }
        else
        {
            break;
        }
    }

end:
    emit sendMsg(0, "读卡结束");

out:
    emit sendMsg(mode, data); //将数据发送到界面
}

bool CardReader::readBlockT10(int b, QByteArray &buf, QByteArray &key)
{
    if (b%4 == 0)//读新扇区前教研密钥
    {
        if (!authenT10(b, key, 0))
            return false;
    }

    if (dc_read(t10dev, b, (unsigned char*)buf.data()) < 0)
    {
        emit sendMsg(0, "读扇区失败");
        return false;
    }

    return true;
}

bool CardReader::authenT10(int b, QByteArray &key, int type)
{
    if(dc_authentication_pass(t10dev, type, b, (uint8_t*)key.data()) < 0)
    {
        sendMsg(0, "密钥认证失败");
        return false;
    }

    return true;
}

void CardReader::writeT10(QByteArray &data, QByteArray &key, QByteArray &blk3, int mode)
{
    QByteArray buf;
    int pos;
    int b;
    int ktype1 = 0;
    QByteArray keyb;
    int err = 0;
    unsigned long snr;

    if (!openDevT10())
        return;

    if (dc_card(t10dev, 0, &snr) < 0)
    {
        sendMsg(0, "寻卡失败");
        return;
    }

    sendMsg(0, "正在写卡");

    keyb = key;
    if (mode == 1)
    {
        ktype1 = 4;
        keyb = blk3.right(6);
    }
    else if (mode == 3)
    {
        keyb = blk3.right(6);
    }
    else if (mode == 4)
    {
        ktype1 = 4;
    }

    if (mode > 2)
    {
        writeBlockT10(4, data, key, ktype1);
        writeBlockT10(7, blk3, key, ktype1);
    }

    for (b = 8, pos = 16; pos < data.size(); b++)
    {
        buf = data.mid(pos, 16);
        if (b == (((b+1)/4)*4 - 1))
            continue;

        if ((b%4 == 0) && (mode == 1 || mode == 3))
        {
            authenT10(b, key, 0);
            if (!writeBlockT10(b + 3, blk3, key, 0))
                err ++;
        }

        if (!writeBlockT10(b, buf, keyb, 4))
            err ++;

        pos += 16;
    }

    if (err)
    {
        sendMsg(0, "写卡结束，有扇区写入异常，请读卡确认");
    }
    else
    {
        sendMsg(0, "写卡结束");
    }
}

bool CardReader::writeBlockT10(int b, QByteArray &buf, QByteArray &key, int type)
{
    if (buf.size() == 0)
        return true;

    if (b%4 == 0)
    {
        if (!authenT10(b, key, type))
            return false;
    }

    if(dc_write(t10dev, b, (uint8_t*)buf.data()) < 0)
    {
        sendMsg(0, "写扇区异常");
        return false;
    }

    return true;
}
#endif

#ifdef __R6DEV
bool CardReader::openDev()
{
    bool ret = false;

     if (r6dev != INVALID_HANDLE_VALUE)
         return true;

    if (mw_dev_openReader((INT8*)"USB1", &r6dev, 2, 0) == 0)
        ret = true;

    return ret;
}

bool CardReader::scanCard()
{
    unsigned char uid[50];

    if (mw_mifare_openCard(r6dev, 0, uid) == 0)
        return true;

    return false;
}

void CardReader::read(int mode)
{
    QByteArray buf(16, 0);
    QByteArray key(6, 0);
    QByteArray data;

    if (!openDev())
    {
        sendMsg(0, "打开读卡器失败");
        return;
    }

    enterCard();

    if (!scanCard())
    {
        sendMsg(0, "寻卡失败");
        return;
    }

    sendMsg(0, "正在读卡");
    if (!authen(4, key, KEYA))
    {
        sendMsg(0, "认证失败(KEYA)");
        goto _err;
    }
    if (!readBlock(4, buf)) //卡号区
        goto _err;

    data += buf;
    if (mode == 1) //只读卡号区
    {
        goto out;
    }

    for (int b = 8; b < 64; b ++) //1扇区不用,共64块
    {
        if (b == (((b+1)/4)*4 - 1))
            continue;//跳过控制块
        if (b % 4 == 0)
        {
            if (!authen(b, key, KEYA))
                break;
        }
        if (readBlock(b, buf))
        {
            if (buf.at(0) == 0)
                break;

            data += buf;
        }
        else
        {
            break;
        }
    }

out:
    emit sendMsg(mode, data); //将数据发送到界面

_err:
    cleanup();
    emit sendMsg(0, "读卡结束");
}

bool CardReader::readBlock(int b, QByteArray &buf)
{
    if (mw_mifare_read(r6dev, b, (UINT8*)buf.data()) == 0)
        return true;

    return false;
}

bool CardReader::authen(int b, QByteArray &key, KeyType type)
{
    int t;

    t = (type == KEYA)? 0 : 1;

    if (mw_mifare_authentication(r6dev, t, b, (UINT8*)key.data()) == 0)
        return true;

    return false;
}

/*
    mode :1 - 用KeyA写其他区
         :2 - 用KeyB修改其他区
         :3 - 用KeyA写所有区
         :4 - 用KeyB修改卡号区
*/
void CardReader::write(QByteArray &data, QByteArray &key,
                       QByteArray &blk3, int mode)
{
    QByteArray buf;
    int pos;
    int b;
    KeyType ktype1 = KEYA;
    QByteArray keyb;
    int err = 0;

    if (!openDev())
    {
        sendMsg(0, "打开读卡器失败");
        return;
    }

    if (!scanCard())
    {
        sendMsg(0, "寻卡失败");
        return;
    }

    sendMsg(0, "正在写卡");

    keyb = key;
    if (mode == 1)
    {
        ktype1 = KEYB;
        keyb = blk3.right(6);
    }
    else if (mode == 3)
    {
        keyb = blk3.right(6);
    }
    else if (mode == 4)
    {
        ktype1 = KEYB;
    }

    if (mode > 2)
    {
        if (!authen(4, key, ktype1))
            return;
        /* 修改卡号 */
        writeBlock(4, data);
        /* 修改控制码 */
        writeBlock(7, blk3);
    }

    /* 其他信息区 */
    for (b = 8, pos = 16; pos < data.size(); b++)
    {
        buf = data.mid(pos, 16);

        if (b == (((b+1)/4)*4 - 1))
            continue;//跳过控制块
        /* 先修改控制块为KEYB写KEYA读和新的Key */
        if ((b%4 == 0) && (mode == 1 || mode == 3))
        {
            authen(b, key, KEYA);
            if (!writeBlock(b + 3, blk3))
                err ++;
        }

        if (b%4 == 0)
        {
            if (!authen(b, keyb, KEYB))
                err ++;
        }

        if (!writeBlock(b, buf))
            err ++;

        pos += 16;
    }

    if (err)
    {
        sendMsg(0, "写卡结束，有扇区写入异常，请读卡确认");
    }
    else
    {
        sendMsg(0, "写卡结束");
    }

    cleanup();
}

void CardReader::cleanup()
{
    mw_mifare_closeCard(r6dev);
}

bool CardReader::writeBlock(int b, QByteArray &buf)
{
    if (mw_mifare_write(r6dev, b, (UINT8*)buf.data()) == 0)
        return true;

    return false;
}

void CardReader::exitCard()
{

}

void CardReader::enterCard()
{

}
#endif

#ifdef __CRTDEV
void CardReader::read(int mode)
{
    QByteArray buf(16, 0);
    QByteArray key(6, 0);
    QByteArray data;

    if (!openDev())
    {
        sendMsg(0, "打开读卡器失败");
        return;
    }

    enterCard();

    if (!scanCard())
    {
        sendMsg(0, "寻卡失败");
        return;
    }

    sendMsg(0, "正在读卡");
    if (!authen(4, key, KEYA))
    {
        sendMsg(0, "认证失败(KEYA)");
        goto _err;
    }
    if (!readBlock(4, buf)) //卡号区
        goto _err;

    data += buf;
    if (mode == 1) //只读卡号区
    {
        goto out;
    }

    for (int b = 8; b < 64; b ++) //1扇区不用,共64块
    {
        if (b == (((b+1)/4)*4 - 1))
            continue;//跳过控制块
        if (b % 4 == 0)
        {
            if (!authen(b, key, KEYA))
                break;
        }
        if (readBlock(b, buf))
        {
            if (buf.at(0) == 0)
                break;

            data += buf;
        }
        else
        {
            break;
        }
    }

out:
    emit sendMsg(mode, data); //将数据发送到界面

_err:
    cleanup();
    emit sendMsg(0, "读卡结束");
}

/*
    mode :1 - 用KeyA写其他区
         :2 - 用KeyB修改其他区
         :3 - 用KeyA写所有区
         :4 - 用KeyB修改卡号区
*/
void CardReader::write(QByteArray &data, QByteArray &key,
                       QByteArray &blk3, int mode)
{
    QByteArray buf;
    int pos;
    int b;
    KeyType ktype1 = KEYA;
    QByteArray keyb;
    int err = 0;

    if (!openDev())
    {
        sendMsg(0, "打开读卡器失败");
        return;
    }

    if (!scanCard())
    {
        sendMsg(0, "寻卡失败");
        return;
    }

    sendMsg(0, "正在写卡");

    keyb = key;
    if (mode == 1)
    {
        ktype1 = KEYB;
        keyb = blk3.right(6);
    }
    else if (mode == 3)
    {
        keyb = blk3.right(6);
    }
    else if (mode == 4)
    {
        ktype1 = KEYB;
    }

    if (mode > 2)
    {
        authen(4, key, ktype1);
        /* 修改卡号 */
        writeBlock(4, data);
        /* 修改控制码 */
        writeBlock(7, blk3);
    }

    /* 其他信息区 */
    for (b = 8, pos = 16; pos < data.size(); b++)
    {
        buf = data.mid(pos, 16);

        if (b == (((b+1)/4)*4 - 1))
            continue;//跳过控制块
        /* 先修改控制块为KEYB写KEYA读和新的Key */
        if ((b%4 == 0) && (mode == 1 || mode == 3))
        {
            authen(b, key, KEYA);
            if (!writeBlock(b + 3, blk3))
                err ++;
        }

        if (b%4 == 0)
        {
            if (!authen(b, keyb, KEYB))
                err ++;
        }

        if (!writeBlock(b, buf))
            err ++;

        pos += 16;
    }

    if (err)
    {
        sendMsg(0, "写卡结束，有扇区写入异常，请读卡确认");
    }
    else
    {
        sendMsg(0, "写卡结束");
    }
out:
    cleanup();
}

bool CardReader::openDev()
{
    if (hDev != INVALID_HANDLE_VALUE)
        return true;
    hDev = CommOpen((char*)"COM1");
    if (hDev == INVALID_HANDLE_VALUE)
        return false;

    return true;
}

bool CardReader::scanCard()
{
    if (RF_DetectCard(hDev) == 0)
        return true;

    return false;
}

bool CardReader::readBlock(int b, QByteArray &buf)
{
    BYTE len = 16;
    int ret;

    ret = RF_ReadBlock(hDev, b/4, b%4, &len, (BYTE*)buf.data());
    if (ret == 0)
        return true;
    else
        return false;
}

bool CardReader::authen(int b, QByteArray &key, KeyType type)
{
    BYTE t;

    t = (type == KEYA)? 0 : 1;

    if (RF_LoadSecKey(hDev, b/4, t, 6, (BYTE*)key.data()) == 0)
        return true;

    return false;
}

void CardReader::cleanup()
{

}

bool CardReader::writeBlock(int b, QByteArray &buf)
{
    BYTE len = 16;
    int ret;

    ret = RF_WriteBlock(hDev, b/4, b%4, len, (BYTE*)buf.data());
    if (ret == 0)
        return true;
    else
        return false;
}

void CardReader::exitCard()
{
    if (hDev == INVALID_HANDLE_VALUE)
        return;

    CRT310_MovePosition(hDev, 0x1);
}

void CardReader::enterCard()
{
    if (hDev == INVALID_HANDLE_VALUE)
        return;

    //CRT310_MovePosition(hDev, 0x3);
}
#endif
